Aller au contenu principal

Widgets

In Flutter, widgets are the foundational building blocks of any application. Every part of a Flutter app, from the most basic UI elements like buttons to complex layouts, is built using widgets. Understanding widgets is key to mastering Flutter development. This page explores what widgets are, their types, and how to use them effectively in your apps.


What is a Widget?

A widget in Flutter is a description of part of a user interface. It can represent:

  • A visible element, like a button, image, or text.
  • An invisible element, like layout padding, alignment, or state management.

Widgets are designed to be immutable, meaning they cannot change directly once created. Instead, when the state of a widget changes, Flutter creates a new widget to reflect the changes.

Example:

app.dart
import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {

Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Widget Example',
home: Scaffold(
appBar: AppBar(
title: Text('Hello Flutter!'),
),
body: Center(
child: Text('This is a simple widget!'),
),
),
);
}
}

In this example:

  • Text, Center, AppBar, and Scaffold are widgets that describe parts of the UI.
  • The Text widget renders a simple text string on the screen.

Types of Widgets

Flutter provides two main types of widgets:

  1. Stateless Widgets
  2. Stateful Widgets

1. Stateless Widgets

Stateless widgets do not change once created. They are immutable and only describe part of the UI without managing any state.

Example of a Stateless Widget:

app.dart
import 'package:flutter/material.dart';

class MyStatelessWidget extends StatelessWidget {

Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(16.0),
color: Colors.blue,
child: Text('I am a stateless widget'),
);
}
}

void main() {
runApp(MyStatelessWidget());
}

Here:

  • The Text widget inside a Container is rendered and never changes.
  • Even if the widget is rebuilt due to UI updates, the widget’s structure remains the same.

Further Reading: StatelessWidget Documentation


2. Stateful Widgets

Stateful widgets can change over time. They manage state, which is the information (data) that can be read synchronously when the widget is built and might change during the widget's lifecycle.

Example of a Stateful Widget:

app.dart
import 'package:flutter/material.dart';

class MyStatefulWidget extends StatefulWidget {

_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;

void _incrementCounter() {
setState(() {
_counter++;
});
}


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Stateful Widget Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Button pressed $_counter times'),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment Counter'),
),
],
),
),
);
}
}

void main() {
runApp(MyStatefulWidget());
}

In this example:

  • Stateful widgets manage the _counter value, which updates every time the button is pressed.
  • The setState method tells Flutter that the widget’s state has changed, triggering a rebuild to reflect the updated UI.

Further Reading: StatefulWidget Documentation


Widget Lifecycle

Stateful widgets have a lifecycle that allows developers to interact with their state at different points in time. Key lifecycle methods include:

  • initState(): Called once when the state object is first created.
  • build(): Called every time the widget is rebuilt.
  • dispose(): Called when the state object is removed.

Example: Stateful Widget Lifecycle

app.dart
class MyLifecycleWidget extends StatefulWidget {

_MyLifecycleWidgetState createState() => _MyLifecycleWidgetState();
}

class _MyLifecycleWidgetState extends State<MyLifecycleWidget> {

void initState() {
super.initState();
print("Widget Initialized");
}


Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('Widget Lifecycle Example'),
),
);
}


void dispose() {
print("Widget Disposed");
super.dispose();
}
}

Here, you can see how initState and dispose work at the start and end of the widget’s lifecycle.


Composition: Widgets Inside Widgets

One of Flutter's core principles is that everything is a widget. You can compose widgets together to create complex UIs. For example, building a form might include using TextField, Button, and Form widgets inside a column layout.

Example:

app.dart
import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {

Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Nested Widgets')),
body: Column(
children: <Widget>[
Text('This is a text widget'),
ElevatedButton(
onPressed: () {},
child: Text('This is a button widget'),
),
],
),
),
);
}
}

In this example, the Column widget is a layout widget that arranges its children vertically. The Text and ElevatedButton widgets are composed within the Column.


Widgets in Flutter: Key Concepts

  • Everything is a widget: Layouts, controls, text, and even the app’s root are widgets.
  • Composition over inheritance: Instead of subclassing widgets, you compose widgets from other widgets.
  • Declarative UI: In Flutter, the UI is rebuilt from scratch every time the app's state changes.
  • Immutability: Widgets are immutable. Changes in the UI are handled by creating new widget trees.

Further Reading: Flutter Widget Catalog


Conclusion

Widgets are the heart of any Flutter app. By understanding how stateless and stateful widgets work, you can create dynamic, responsive UIs with ease. From basic UI components like buttons and text to custom layouts and state management, Flutter’s widget system is flexible, powerful, and essential for building cross-platform applications.

Next Steps:

  • Explore the Flutter Widget Catalog to dive deeper into specific widgets.
  • Try building your own stateless and stateful widgets to practice UI composition and state management.